package com.liuh.fram.util;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.jfinal.kit.StrKit;
import com.liuh.fram.err.LocalException;
import com.liuh.fram.err.LocalException.ErrorType;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Request.Builder;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import okio.BufferedSink;

/**
 * @note 
 *       官方示例:https://github.com/square/okhttp/tree/master/samples/guide/src/main
 *       /java/com/squareup/okhttp
 *       中文翻译：http://www.cnblogs.com/ct2011/p/4001708.html
 *       joc:http://square.github.io/okhttp/javadoc/
 *       wiki:https://github.com/square/okhttp/wiki/Recipes
 * */
public class OkHttpKit {

	private static final OkHttpClient mOkHttpClient = new OkHttpClient();

	public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType
			.parse("text/x-markdown; charset=utf-8");
	private static final MediaType MEDIA_TYPE_PNG = MediaType
			.parse("image/png");

	static {
		mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS);
		mOkHttpClient.setReadTimeout(15, TimeUnit.SECONDS);
		mOkHttpClient.setWriteTimeout(15, TimeUnit.SECONDS);
	}

	/**
	 * @note 构造请求头参数
	 * @author liuh
	 * */
	public static Builder buildRequestPara(String url, String keya) {
		Builder build = new Request.Builder();
		if (StrKit.notBlank(keya)) {
			build.header("keya", keya);
		}
		build.url(url);
		build.header(
				"User-Agent",
				"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22");
		return build;
	}

	/**
	 * 不会开启异步线程。
	 * 
	 * @param request
	 * @return
	 * @throws IOException
	 */
	public static String get(String url, String keya) throws Exception {
		Request request = buildRequestPara(url, keya).build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (!response.isSuccessful()) {
			throw new LocalException(ErrorType.httpErr, response.message());
		}
		return response.body().string();
	}

	/**
	 * @note 提交post String
	 * @author liuh
	 * */
	public static String postStr(String url, String postBody, String keya)
			throws Exception {
		Builder build = buildRequestPara(url, keya);
		build.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody));
		Request request = build.build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (!response.isSuccessful()) {
			throw new LocalException(ErrorType.httpErr, response.message());
		}
		return response.body().string();
	}

	/**
	 * @note 提交post Streaming
	 * @author liuh
	 * */
	public static String postStream(String url, final String postBody,
			String keya) throws Exception {
		Builder build = buildRequestPara(url, keya);
		build.post(new RequestBody() {
			@Override
			public MediaType contentType() {
				return MEDIA_TYPE_MARKDOWN;
			}

			@Override
			public void writeTo(BufferedSink sink) throws IOException {
				sink.writeUtf8(postBody);
			}
		});
		Request request = build.build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (!response.isSuccessful()) {
			throw new LocalException(ErrorType.httpErr, response.message());
		}
		return response.body().string();
	}

	/**
	 * @note 提交post 文件
	 * @author liuh
	 * */
	public static String postFile(String url, File file, String keya)
			throws Exception {
		Builder build = buildRequestPara(url, keya);
		build.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file));
		Request request = build.build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (!response.isSuccessful()) {
			throw new LocalException(ErrorType.httpErr, response.message());
		}
		return response.body().string();
	}

	/**
	 * @note post from表单
	 * @author liuh
	 * */
	public static String postForm(String url, Map<String, String> para,
			String keya) throws Exception {
		Builder build = buildRequestPara(url, keya);
		FormEncodingBuilder formBuild = new FormEncodingBuilder();
		for (Map.Entry<String, String> entry : para.entrySet()) {
			formBuild.add(entry.getKey(), entry.getValue());
		}
		build.post(formBuild.build());
		Request request = build.build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (!response.isSuccessful()) {
			throw new LocalException(ErrorType.httpErr, response.message());
		}
		return response.body().string();
	}

	/**
	 * @note 提交post Multipart
	 * @author liuh
	 * */
	public static String postMultipart(String url, String keya)
			throws Exception {
		Builder build = buildRequestPara(url, keya);
		RequestBody requestBody = new MultipartBuilder()
				.type(MultipartBuilder.FORM)
				.addPart(
						Headers.of("Content-Disposition",
								"form-data; name=\"title\""),
						RequestBody.create(null, "Square Logo"))
				.addPart(
						Headers.of("Content-Disposition",
								"form-data; name=\"image\""),
						RequestBody.create(MEDIA_TYPE_PNG, new File(
								"website/static/logo-square.png"))).build();
		build.post(requestBody);
		Request request = build.build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (!response.isSuccessful()) {
			throw new LocalException(ErrorType.httpErr, response.message());
		}
		return response.body().string();
	}

	/**
	 * 开启异步线程访问网络
	 * 
	 * @param request
	 * @param responseCallback
	 */
	public static void enqueue(Request request, Callback responseCallback) {
		mOkHttpClient.newCall(request).enqueue(responseCallback);
	}

	/**
	 * 开启异步线程访问网络, 且不在意返回结果（实现空callback）
	 * 
	 * @param request
	 */
	public static void enqueue(Request request) {
		mOkHttpClient.newCall(request).enqueue(new Callback() {

			@Override
			public void onResponse(Response response) throws IOException {
				if (!response.isSuccessful()) {
					throw new IOException("Unexpected code " + response);
				}

				System.out.println(response.body().string());
			}

			@Override
			public void onFailure(Request request, IOException e) {
				e.printStackTrace();
			}
		});
	}

}
